/***************************************************************
* gfsConsole : Console to access GFS user-library
*
* @author : Ridho B - 0606101906
* @version : 1.0
*
***************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "gfsGlobal.h"
#include "gfsLibrary.h"

#define MAXWORKINGPATH   600
#define MAXCMDLENGTH  10
#define MAXPARAMS 2
#define MAXPARAMSLENGTH 512
#define BUFFER_SIZE 5000000 // 5MB

// ALL FUNCTION //

char getchar_until_next(char* , int);		/* ANSI function prototype */
void getchar_until_end(char* , int);		/* ANSI function prototype */
void getchar_data_end(char* , int);		/* ANSI function prototype */
void getpswd(char*, int);			/* ANSI function prototype */
void get_full_path(char*, char*, char*);	/* ANSI function prototype */
void get_file_name(char*, char*);		/* ANSI function prototype */
int  select_cmd(char* );			/* ANSI function prototype */
void process_param(char*, char*);		/* ANSI function prototype */
void show_server();				/* ANSI function prototype */
void advance_cursor();

// WORKING PATH //
char strWorkingPath[MAXWORKINGPATH];

// MAIN //
int main()
{
		
	// 	READY	//
	printf("\n\n==========:. TESTING GRID FILE SYSTEM LIBRARY .:==========\n");
	
	// DEFINE VARIABLE //
	char    chInput;               			/* handles user input */
	char    strCmd[MAXCMDLENGTH];			/* String Command, max 10 chr */
	char    strParams01[MAXPARAMSLENGTH];		/* Array of String Params, max 512 chr */
	char    strParams02[MAXPARAMSLENGTH];		/* Array of String Params, max 512 chr */
	char    strUnusdParams[MAXPARAMSLENGTH];	/* Array of String Params that Unused, max 512 chr */
	int     iExit_flag = 0;				/* Flag for exit command*/
	int     iNotValid = 0;				/* Flag for not valid command and operands */
	int     iParams = 1;				/* Number of params */
	int 	iIdx;					/* Index */
	
	// SET PATH FOR ROOT //
	strcpy(strWorkingPath,"/");
	
	// DEBUG ON //
	VERBOSE = 0;

	// GFS VARIABLE //	
	int 		iResult;
	GFS_file    	GFS_file;
	GFS_item 	listGFSItem;
	GFS_server 	listGFSServer;

	// EXECUTE COMMAND //
	while( iExit_flag == 0 ) {
		/* initiate */
		strCmd[0] = 0x00;
		strParams01[0] = 0x00;
		strParams02[0] = 0x00;
		strUnusdParams[0] = 0x00;
		iNotValid = 0;
		
		if(iParams == 1){
			/* Test Case */
			printf("TEST CASE \n");
			printf("1 = init GFS \n");
			printf("2 = init RNS \n");
			printf("3 = open file \n");
			printf("4 = close file \n");
			printf("5 = check end of file \n");
			printf("6 = write file \n");
			printf("7 = read file \n");
			printf("8 = remove file \n");
			printf("9 = read dir \n");
			printf("10 = create dir \n");
			printf("11 = remove dir \n");
			printf("12 = check dir \n");
			printf("13 = remove recursive \n");
			printf("14 = move \n");
			printf("15 = chmod \n");
			printf("16 = get server \n");
			printf("17 = su on \n");
			printf("18 = su off \n");
			printf("19 = su chpwd \n");
			printf("20 = get error\n\n");
			iParams = 0;
		}

		/* Get Command */
		printf(":: X to exit, C show command or insert test case index: ");
		chInput = getchar_until_next(strCmd, MAXCMDLENGTH);
		if(strCmd[0] == 'X' || strCmd[0] == 'x')
			iExit_flag = 1;
		else if(strCmd[0] == 'C' || strCmd[0] == 'c')
			iParams = 1;
		else{
		switch(atoi(strCmd)) {
			case 1: /* init ---------------------------------------------------------init GFS---*/				
				printf("1 = init GFS \n");			
				printf("\n gfs_init_GFS() = %d \n", gfs_init_GFS());
				break;
			case 2: /* init ---------------------------------------------------------init RNS---*/				
				printf("2 = init RNS");			
				printf("\n gfs_init_RNS() = %d \n", gfs_init_RNS());
				break;
			case 3: /* open  ------------------------------------------------------open file----*/
				printf("3 = open file \n");
				printf("gfs_open_file(char *strGFSPath, char *mode, GFS_file *file_ref); \n");
				/* Get Params */
				printf("insert strGFSPath: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Get Params */
				printf("insert mode: ");
				getchar_until_end(strParams02, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_open_file(%s, %s, GFS_file) = %d", strParams01, strParams02, gfs_open_file(strParams01, strParams02, &GFS_file));
				printf(" (GFS_file == NULL) = %d\n", (GFS_file == NULL));
				break;
			case 4: /* close  ----------------------------------------------------close file----*/
				printf("4 = close file \n");
				printf("gfs_close_file(GFS_file file); \n");
				/* Valid library call */
				printf("gfs_close_file(GFS_file) = %d ", gfs_close_file(&GFS_file));
				printf("(GFS_file == NULL) = %d \n", (GFS_file == NULL));
				break;
			case 5: /* end  -----------------------------------------------------end of file----*/
				printf("5 = end of file \n");
				printf("gfs_end_file(GFS_file file); \n");
				/* Valid library call */
				printf("gfs_end_file(GFS_file) = %d \n", gfs_end_file(GFS_file) );
				break;
			case 6: /* write -----------------------------------------------------write file----*/
				printf("6 = write file \n");
				printf("gfs_write_file(GFS_file file, void *buffer, int iSize); \n");
				/* Get Params */
				printf("insert data in buffer: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Get Params */
				printf("insert iSize: ");
				getchar_until_end(strParams02, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_write_file(GFS_file, %s, %d) = %d \n",strParams01, atoi(strParams02), gfs_write_file(GFS_file, strParams01, atoi(strParams02)));
				break;
			case 7: /* read ------------------------------------------------------read file----*/
				printf("7 = read file \n");
				printf("gfs_read_file(GFS_file file, void *buffer, int iSize); \n");
				/* Get Params */
				printf("insert iSize: ");
				getchar_until_end(strParams02, MAXPARAMSLENGTH);
				/* Valid library call */
				iResult = gfs_read_file(GFS_file, strParams01, atoi(strParams02));
				strParams01[iResult] = 0x00;
				printf("gfs_read_file(GFS_file, buffer, %s) = %d\n", strParams02, iResult);
				printf("Buffer readed = %s\n", strParams01);
				break;
			case 8: /* remove --------------------------------------------------remove file----*/
				printf("8 = remove file \n");
				printf("gfs_remove_file(char *strGFSPath); \n");
				/* Get Params */
				printf("insert strGFSPath: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_remove_file(%s) = %d\n", strParams01, gfs_remove_file(strParams01));
				break;
			case 9: /* read --------------------------------------------------------read dir----*/
				printf("9 = read dir \n");
				printf("gfs_read_dir(char *strGFSPath, GFS_item *listGFSItem_ref); \n");
				/* Get Params */
				printf("insert strGFSPath: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Valid library call */
				listGFSItem = NULL;
				printf("gfs_read_dir(%s, listGFSItem) = %d \n", strParams01, gfs_read_dir(strParams01, &listGFSItem));
				printf("dir list: \n");
				GFS_item now=NULL;
				if (listGFSItem != NULL)
				{
					now = listGFSItem;
					while (now)
					{
						printf("%s %s %8lld %s %s %s %s\n", now->type, now->permission, now->size, now->owner, now->created_date, now->modified_date, now->item_name);
						now=now->next;
					}
				}
				break;
			case 10: /* create ---------------------------------------------------create dir----*/
				printf("10 = create dir \n");
				printf("gfs_create_dir(char *strGFSPath); \n");
				/* Get Params */
				printf("insert strGFSPath: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_create_dir(%s) = %d\n", strParams01, gfs_create_dir(strParams01));
				break;
			case 11: /* remove ---------------------------------------------------remove dir----*/
				printf("11 = remove dir \n");
				printf("gfs_remove_dir(char *strGFSPath); \n");
				/* Get Params */
				printf("insert strGFSPath: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_remove_dir(%s) = %d\n", strParams01, gfs_remove_dir(strParams01));
				break;
			case 12: /* check -----------------------------------------------------check dir----*/
				printf("12 = check dir \n");
				printf("gfs_check_dir(char *strGFSPath); \n");
				/* Get Params */
				printf("insert strGFSPath: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_check_dir(%s) = %d\n", strParams01, gfs_check_dir(strParams01));
				break;
			case 13: /* remove recursive------------------------------------remove recursive----*/
				printf("13 = remove recursive \n");
				printf("gfs_remove_recursive(char *strGFSPath); \n");
				/* Get Params */
				printf("insert strGFSPath: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_remove_recursive(%s) = %d\n", strParams01, gfs_remove_recursive(strParams01));
				break;
			case 14: /* move ----------------------------------------------------------move ----*/
				printf("14 = move \n");
				printf("gfs_move(char *strSrcGFSPath, char *strDstGFSPath)); \n");
				/* Get Params */
				printf("insert strSrcGFSPath: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Get Params */
				printf("insert strDstGFSPath: ");
				getchar_until_end(strParams02, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_move(%s, %s) = %d\n", strParams01, strParams02, gfs_move(strParams01, strParams02));
				break;
			case 15: /* change mode --------------------------------------------change mode-----*/
				printf("15 = change mode \n");
				printf("gfs_change_mode(char *strSrcGFSPath, char *mode); \n");
				/* Get Params */
				printf("insert strGFSPath: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Get Params */
				printf("insert mode: ");
				getchar_until_end(strParams02, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_change_mode(%s, %s) = %d \n", strParams01, strParams02, gfs_change_mode(strParams01, strParams02));
				break;
			case 16: /* get server -----------------------------------------------get server----*/
				printf("16 = get server \n");
				printf("gfs_get_server(GFS_server *listGFSServer_ref); \n");
				/* Valid library call */
				listGFSServer = NULL;
				printf("gfs_get_server(listGFSServer) = %d\n", gfs_get_server(&listGFSServer));
				printf("list server:\n");
		  		GFS_server nw=NULL;
				if (listGFSServer != NULL)
				{
					nw = listGFSServer;
					while (nw)
					{				
						printf("GFS-server : %s | %lld/%lld | %s\n", nw->hostname, nw->used, nw->total, nw->online);
						nw=nw->next;
					}
				}
				break;
			case 17: /* su on ---------------------------------------------------------su on----*/
				printf("17 = su on \n");
				printf("gfs_SU_on(char *strPassword); \n");
				/* Get Params */
				printf("insert strPassword: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_SU_on(%s) = %d \n", strParams01, gfs_SU_on(strParams01));
				break;
			case 18: /* su off -------------------------------------------------------su off----*/
				printf("18 = su off \n");
				printf("gfs_SU_off() = %d \n", gfs_SU_off());
				break;
			case 19: /* su chpwd ---------------------------------------------------su chpwd----*/
				printf("19 = su chpwd \n");
				printf("gfs_SU_change_pwd(char *strOldPassword, char *strNewPassword); \n");
				/* Get Params */
				printf("insert strOldPassword: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Get Params */
				printf("insert strNewPassword: ");
				getchar_until_end(strParams02, MAXPARAMSLENGTH);
				/* Valid library call */
				printf("gfs_SU_change_pwd(%s, %s) = %d \n", strParams01,strParams02, gfs_SU_change_pwd(strParams01,strParams02));
				break;
			case 20: /* get error -------------------------------------------------get error----*/
				printf("20 = get error \n");
				printf("gfs_get_error(int iStatus); \n");
				/* Get Params */
				printf("insert int process status: ");
				getchar_until_end(strParams01, MAXPARAMSLENGTH);
				/* Valid library call */
				char *strErr = gfs_get_error(atoi(strParams01));
				printf("gfs_get_error(%d) = %s \n", atoi(strParams01), strErr);
				break;
			default:
				/* exit --------------------------------------------------------------exit--*/
				iExit_flag = 1;
				if(chInput != '\n')
					getchar_until_end(strUnusdParams, MAXPARAMSLENGTH);
				break;
			}
			}
	}
	return 0;
}

// SOME FUNCTION //
/**********************************************************************************
* getchar_until_next : store char from getchar() to string (passing by reference)
* until space or new line
* @params : String to store, Max length of string 
* @return : The last getchar()
***********************************************************************************/
char getchar_until_next(char *strResult, int iMaxLength ){
	int iChar_count = 0;
	char chInput = getchar();
		while( (chInput != ' ') && (chInput != '\n') &&  (iChar_count < iMaxLength)) {
			strResult[iChar_count++] = chInput;
			chInput = getchar();
		}
		strResult[iChar_count] = 0x00; /* null terminate strCmd */
		return chInput;
}
/**********************************************************************************
* getchar_until_end : store char from getchar() to string (passing by reference)
* until new line (end of input line)
* @params : String to store, Max length of string 
* @return : void
***********************************************************************************/
void getchar_until_end(char *strResult, int iMaxLength){
	int iChar_count = 0;
	char chInput = getchar();
		while((chInput != '\n') &&  (iChar_count < iMaxLength)) {
			strResult[iChar_count++] = chInput;
			chInput = getchar();
		}
		strResult[iChar_count] = 0x00; /* null terminate strCmd */	
}	
/**********************************************************************************
* getchar_until_end : store char from getchar() to string (passing by reference)
* until new line (end of input line)
* @params : String to store, Max length of string 
* @return : void
***********************************************************************************/
void getchar_data_end(char *strResult, int iMaxLength){
	int iChar_count = 0;
	char chInput = getchar();
		while((chInput != '\n') &&  (iChar_count < iMaxLength)) {
			strResult[iChar_count++] = chInput;
			chInput = getchar();
		}
		strResult[iChar_count] = 0x00; /* null terminate strCmd */	
}	
